package com.streaminggbs.common.job;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.streaminggbs.common.constants.Constants;
import com.streaminggbs.common.utils.DateUtil;
import com.streaminggbs.common.utils.RedisUtil;
import com.streaminggbs.entity.DeviceChannelInfo;
import com.streaminggbs.entity.DeviceInfo;
import com.streaminggbs.entity.RecordFile;
import com.streaminggbs.entity.RecordPlan;
import com.streaminggbs.interfaces.*;
import com.streaminggbs.model.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.util.*;

/**
 * 检测设备无客户端连接时超时自动关闭
 */
@Component
@Slf4j
public class StreamCheckJob {
    @Autowired
    RestTemplate restTemplate;
    @Autowired
    SysParamSetService sysParamSetService;
    @Autowired
    Gb28181Service gb28181Service;
    @Autowired
    RedisUtil redisUtil;
    @Autowired
    DeviceChannelInfoService deviceChannelInfoService;
    @Autowired
    DeviceInfoService deviceInfoService;

    /**
     * 定时更新离线设备
     */
    @Scheduled(initialDelayString = "${schedule.offlineCheckTimeOut}", fixedRateString = "${schedule.offlineCheckTimeOut}")
    public void updateCarStatus() {
        log.info("定时更新离线设备开始:{}",System.currentTimeMillis());
        try {
            HttpHeaders headers = new HttpHeaders();
            MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
            headers.setContentType(type);
            headers.add("Accept", MediaType.APPLICATION_JSON.toString());
            JSONObject param = new JSONObject();
            HttpEntity<JSONObject> formEntity = new HttpEntity<>(param, headers);
            String deviceVideoServiceUrl = sysParamSetService.pick().getVideoServerUrl();
            ResponseEntity<JSONObject> responseEntity = restTemplate.postForEntity(deviceVideoServiceUrl+Constants.PLATFORM_DEVICE_CHANNEL_LIST, formEntity, JSONObject.class);
            log.info("获取到的设备数据{}:{}",DateUtil.formatDate(new Date()), JSONObject.toJSONString(responseEntity));
            // 获取到的设备信息 然后进行一个状态的判断
            List<DeviceChannelInfo> batchUpdateAllChannel = Lists.newLinkedList();
            List<DeviceInfo> batchUpdateAllDevice = Lists.newLinkedList();
            JSONObject resJsonObject = responseEntity.getBody();
            if (resJsonObject.getIntValue("DeviceCount") <= 0) {
                log.info("当前需要更新状态的设备不存在!");
                return;
            }
            // 获取在线设备树
            DeviceInfo deviceInfo = new DeviceInfo();
            List<DeviceInfo> allOnlineDevice = deviceInfoService.select(deviceInfo);
            DeviceChannelInfo deviceChannelInfo = new DeviceChannelInfo();
            List<DeviceChannelInfo> allOnlineDeviceChannel = deviceChannelInfoService.select(deviceChannelInfo);
            List<JSONObject> deviceList = resJsonObject.getJSONArray("DeviceList").toJavaList(JSONObject.class);
            List<JSONObject> channelList = Lists.newLinkedList();
            for (DeviceInfo queryDeviceInfo : allOnlineDevice) {
                // 验证list是否存在当前的设备号
                JSONObject deviceJson = deviceList.stream().filter(v -> v.getString("id").equals(queryDeviceInfo.getDevice())).findFirst().orElse(null);
                if (null == deviceJson) {
                    DeviceInfo updateDeviceInfo = new DeviceInfo();
                    updateDeviceInfo.setId(queryDeviceInfo.getId());
                    updateDeviceInfo.setStatus(0);
                    batchUpdateAllDevice.add(updateDeviceInfo);
                } else {
                    Integer deviceStatus = (deviceJson.containsKey("Online") && deviceJson.getString("Online").equals(Constants.PLATFORM_DEVICE_ONLINE) ? 1 : 0);
                    if (queryDeviceInfo.getDevice().equals(deviceJson.getString("id"))
                            && !queryDeviceInfo.getStatus().equals(deviceStatus)) {
                        DeviceInfo updateDeviceInfo = new DeviceInfo();
                        updateDeviceInfo.setId(queryDeviceInfo.getId());
                        updateDeviceInfo.setStatus(deviceStatus);
                        batchUpdateAllDevice.add(updateDeviceInfo);
                    }
                    if (deviceJson.getIntValue("ChannelCount") > 0) {
                        List<JSONObject> jsonObjectList = deviceJson.getJSONArray("ChannelList").toJavaList(JSONObject.class);
                        if(jsonObjectList!=null && jsonObjectList.size()>0) {
                            for(JSONObject channel:jsonObjectList){
                                channel.put("localDeviceId",queryDeviceInfo.getId());
                            }
                            channelList.addAll(jsonObjectList);
                        }
                    }
                }
            }
            if (!channelList.isEmpty()) {
                for (DeviceChannelInfo queryDeviceChannelInfo : allOnlineDeviceChannel) {
                    JSONObject deviceChannelJson = channelList.stream().filter(a -> a.getString("id").equals(queryDeviceChannelInfo.getChannel()) && a.getString("localDeviceId").equals(queryDeviceChannelInfo.getDeviceid())).findFirst().orElse(null);
                    if (null == deviceChannelJson) {
                        DeviceChannelInfo updateDeviceChannelInfo = new DeviceChannelInfo();
                        updateDeviceChannelInfo.setId(queryDeviceChannelInfo.getId());
                        updateDeviceChannelInfo.setStatus(0);
                        batchUpdateAllChannel.add(updateDeviceChannelInfo);
                    } else {
                        int status = (deviceChannelJson.containsKey("status") && deviceChannelJson.getString("status").equals(Constants.PLATFORM_DEVICE_CHANNEL_ONLINE) ? 1 : 0);
                        if (queryDeviceChannelInfo.getChannel().equals(deviceChannelJson.getString("id"))
                                && queryDeviceChannelInfo.getDeviceid().equals(deviceChannelJson.getString("localDeviceId"))
                                && !queryDeviceChannelInfo.getStatus().equals(status)) {
                            DeviceChannelInfo updateDeviceChannelInfo = new DeviceChannelInfo();
                            updateDeviceChannelInfo.setDeviceid(queryDeviceChannelInfo.getDeviceid());
                            updateDeviceChannelInfo.setId(queryDeviceChannelInfo.getId());
                            updateDeviceChannelInfo.setStatus(status);
                            batchUpdateAllChannel.add(updateDeviceChannelInfo);
                        }
                    }
                }
            }
            if (!batchUpdateAllDevice.isEmpty()) {
                log.info("更新设备状态的总数:{}", batchUpdateAllDevice.size());
                for (DeviceInfo updateDeviceInfo : batchUpdateAllDevice) {
                    deviceInfoService.updateNotNull(updateDeviceInfo);
                }
            }
            if (!batchUpdateAllChannel.isEmpty()) {
                log.info("更新设备通道状态的总数:{}", batchUpdateAllChannel.size());
                for (DeviceChannelInfo updateDeviceChannelInfo : batchUpdateAllChannel) {
                    deviceChannelInfoService.updateNotNull(updateDeviceChannelInfo);
                }
            }
            log.info("定时更新离线设备结束:{}", System.currentTimeMillis());
        } catch (Exception e) {
            log.error("系统异常!",e);
        }
    }

    public void saveRecord(RecordPlan recordPlan) {
        try {
            ScheduleModel scheduleModel = new ScheduleModel();
            scheduleModel.setDevice(recordPlan.getDevice());
            scheduleModel.setChannel(recordPlan.getChannel());
            Boolean startSchedule = false;
            List<ScheduleTimeModel> modelTimesList = new ArrayList<>();
            if(StringUtils.isNotEmpty(recordPlan.getContent())) {
               List<PlanData> planDataList= JSONArray.parseArray(recordPlan.getContent(), PlanData.class);
               if(planDataList!=null && planDataList.size()>0) {

                   scheduleModel.setTimes(modelTimesList);
                   for(PlanData item:planDataList) {
                       ScheduleTimeModel modelTimes = new ScheduleTimeModel();
                       modelTimesList.add(modelTimes);
                       modelTimes.setDay(item.getDay());
                       modelTimes.setSchedule(1);
                       if(item.getDay()==7) {
                           modelTimes.setDay(0);
                       }
                       if(item.getTimes()!=null && item.getTimes().size()>0) {
                           List<ScheduleTimeRangeHourModel> modelTimeRangeHourList = new ArrayList<>();
                           for(PlanTimeData itemTime:item.getTimes()) {
                               ScheduleTimeRangeHourModel modelTimeRangeHourStart = new ScheduleTimeRangeHourModel();
                               modelTimeRangeHourStart.setHour(itemTime.getStime());
                               modelTimeRangeHourStart.setMin(0);
                               modelTimeRangeHourStart.setSecond(0);
                               modelTimeRangeHourList.add(modelTimeRangeHourStart);
                               //结束
                               ScheduleTimeRangeHourModel modelTimeRangeHourEnd = new ScheduleTimeRangeHourModel();
                               modelTimeRangeHourEnd.setHour(itemTime.getEtime());
                               modelTimeRangeHourEnd.setMin(59);
                               modelTimeRangeHourEnd.setSecond(59);
                               modelTimeRangeHourList.add(modelTimeRangeHourEnd);
                               startSchedule = true;
                           }
                           modelTimes.setRanges(modelTimeRangeHourList);
                       }
                   }
               }
            }
            if(startSchedule==true) {
                gb28181Service.startSchedule(recordPlan.getDevice(), recordPlan.getChannel(),JSONArray.parseArray(JSON.toJSONString(modelTimesList)));
            }else {
                gb28181Service.stopSchedule(recordPlan.getDevice(), recordPlan.getChannel());
            }
        } catch (Exception e) {
            log.error("", e);
        }
    }

    public synchronized void removeRecord(String device, String channel) {
        try {
            gb28181Service.stopSchedule(device, channel);
        } catch (Exception e) {
            log.error("", e);
        }
    }

}
